package org.sgx.dao;

import java.sql.ResultSet;
import java.util.List;

import org.sgx.dao.model.Model;
import org.sgx.dao.util.OrderedMap;
import org.sgx.dao.util.SQLUtil;
import org.sgx.dao.util.SQLUtil.StringMatcher;


public interface Dao <T extends Model> extends Connectated {
	
	public static interface ModelAccessor<E extends Model> {
		Object get(E model, String name);
		void set(E model, String name, Object value);
	}
	
	T get(Long id) throws DaoException;
//	T get(long id, String locale) throws DaoException;
	/**
	 * implementation code :
	 * <pre>
	long id = incrementCounter();
	t.setModelId(id);
	save(t, true);
	return id;
	 * </pre>
	 * @param t - object to add. its setModelId will be called with a unique id
	 * @return
	 * @throws DaoException
	 */
	Long add(T t)  throws DaoException;
//	public long add(T t, String locale) throws DaoException;
	Long[] add(T ...t)  throws DaoException;
	void update(T t) throws DaoException;
	T remove(long id) throws DaoException;
	T remove(T t) throws DaoException;;
	
	/**
	 * build an object model from database
	 * @param id
	 * @return
	 * @throws DaoException
	 */
	T load(Long id) throws DaoException;
//	T load(long id, String locale) throws DaoException;
	
	/**
	 * only for internal use
	 * can be used for iterating over a result set for build a list of objects. 
	 * @return null if the result set has no more element.
	 */
	T buildFrom(ResultSet rs) throws DaoException;
	
	List<T> listAll() throws DaoException;
	
	
//	/**
//	 * 
//	 * @param t
//	 * @param insert - if true the statement will be an sql insert and an id will be unique generated, assignated, and returned. 
//	 * Else it will be an update statement;
//	 * @return
//	 */
//	long save(T t, boolean insert) throws DaoException;
	
	String getColumnIdName();
	String getTableName();
	OrderedMap<String, String> getSQLColumns();
	ModelAccessor<T> getModelAccessor();
	
	Class<T> getModelClass() throws ClassNotFoundException;
	public String getModelClassName();
	T instantiateModel() throws DaoException;
	void dropTable() throws DaoException;
	
	/**
	 * if do not exists, create the sql table that will hold objects for this dao.
	 * be sure that all data in sqlColumns and modelAccessor fields are already provided. 
	 * @throws DaoException 
	 */
	void createTable() throws DaoException;
	List<T> get(List<Long> ids) throws DaoException;
	
	
	
	List<T> search(OrderedMap<String, String> keywords, SQLUtil.StringMatcher matcher, String operator) throws DaoException;
	List<T> search(OrderedMap<String, String> keywords, String operator) throws DaoException;
	List<T> search(OrderedMap<String, String> keywords) throws DaoException;
//	List<T> search(OrderedMap<String, String> keywords, String locale) throws DaoException;
	
	Long setLocale(T t, String locale) throws DaoException;
//	boolean updateLocale(T t, String locale) throws DaoException;
	T getLocale(Long id, String locale) throws DaoException;
	/**
	 * if object t is not defined in some locale of allLocales array, then it is added so t will be the localized object for those locales. does nothing if t is already localized.
	 * @throws DaoException 
	 */
	public void checkAllLocales(T t, String[] allLocales) throws DaoException;	
	List<T>getAllLocale(String locale) throws DaoException;
	List<T> getLocales(List<Long>ids, String locale) throws DaoException;
	List<T> searchLocale(OrderedMap<String, String> keywords, SQLUtil.StringMatcher matcher, String operator, String locale) throws DaoException;
	List<T> searchLocale(OrderedMap<String, String> keywords, String locale) throws DaoException;
}

